package com.sh.cloudrender.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sh.cloudrender.application.dto.access.AccessDTO;
import com.sh.cloudrender.infrastructure.dal.dao.AccessDao;
import com.sh.cloudrender.infrastructure.dal.dao.UserEngineRelDao;
import com.sh.cloudrender.infrastructure.dal.entity.AccessDO;
import com.sh.cloudrender.infrastructure.dal.entity.EngineDO;
import com.sh.cloudrender.infrastructure.dal.entity.UserDO;
import com.sh.cloudrender.infrastructure.dal.entity.UserEngineRel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Repository
public class AccessRepoImpl implements AccessRepo {

    @Autowired
    private AccessDao accessDao;

    @Autowired
    private UserEngineRelDao userEngineRelDao;

    @Override
    @Transactional
    public boolean save(String userId, AccessDTO accessDTO) {
        AccessDO accessDO = new AccessDO();
        BeanUtils.copyProperties(accessDTO, accessDO);
        accessDO.setUserId(userId);
        return accessDao.save(accessDO);
    }

    @Override
    public List<AccessDTO> findByUserId(String userId) {
        QueryWrapper<AccessDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        List<AccessDO> accessDOS = accessDao.list(queryWrapper);
        if (CollectionUtils.isEmpty(accessDOS)) {
            return null;
        }

        return accessDOS.stream().map(item -> parse(item)).collect(Collectors.toList());
    }

    @Override
    public AccessDTO findByKey(String userId, String accessKey) {
        QueryWrapper<AccessDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId).eq("access_key", accessKey);
        AccessDO accessDO = accessDao.getOne(queryWrapper);
        if (accessDO == null) {
            return null;
        }

        return parse(accessDO);
    }

    @Override
    @Transactional
    public boolean deleteByUserId(String userId) {
        QueryWrapper<AccessDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        return accessDao.remove(queryWrapper);
    }

    @Override
    @Transactional
    public boolean disableByKey(String userId, String accessKey) {
        UpdateWrapper<AccessDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", userId).set("disable", 1);
        if (StringUtils.isNotBlank(accessKey)) {
            updateWrapper.eq("access_key", accessKey);
        }
        return accessDao.update(updateWrapper);
    }

    @Override
    @Transactional
    public boolean updateLastUsedTime(String userId, String accessKey) {
        UpdateWrapper<AccessDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", userId).eq("access_key", accessKey).set("last_used_time", new Date());
        return accessDao.update(updateWrapper);
    }

    @Override
    @Transactional
    public List<AccessDTO> getAccessKeyByEngineId(String engineId) {
        QueryWrapper<UserEngineRel> queryUserEngineRelWrapper = new QueryWrapper<>();
        queryUserEngineRelWrapper.eq("engine_id", engineId);
        List<UserEngineRel> engineRels = userEngineRelDao.list(queryUserEngineRelWrapper);
        if (CollectionUtils.isEmpty(engineRels)) {
            return null;
        }

        QueryWrapper<AccessDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", engineRels.stream().map(UserEngineRel::getUserId)
                .collect(Collectors.toList()).toArray());
        List<AccessDO> accessDOS = accessDao.list(queryWrapper);
        if (CollectionUtils.isEmpty(accessDOS)) {
            return null;
        }

        return accessDOS.stream().map(item -> parse(item)).collect(Collectors.toList());
    }


    private AccessDTO parse(AccessDO accessDO) {
        AccessDTO dto = new AccessDTO();
        BeanUtils.copyProperties(accessDO, dto);
        return dto;
    }
}
